package com.yxw.yxnet_cd_center.customer_service.service.impl;

import com.yxw.yxnet_cd_center.common.constant.CommonConstant;
import com.yxw.yxnet_cd_center.customer_service.entity.*;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yxw.yxnet_cd_center.common.dto.PageVO;
import com.yxw.yxnet_cd_center.common.exception.BaseException;
import com.yxw.yxnet_cd_center.common.utils.PasswordUtil;
import com.yxw.yxnet_cd_center.common.utils.PinyinUtill;
import com.yxw.yxnet_cd_center.customer_service.dto.PasswordDTO;
import com.yxw.yxnet_cd_center.customer_service.dto.UserEmpDTO;
import com.yxw.yxnet_cd_center.customer_service.dto.UserEmpQueryDTO;
import com.yxw.yxnet_cd_center.customer_service.dto.UserEmpUpdateDTO;
import com.yxw.yxnet_cd_center.customer_service.mapper.*;
import com.yxw.yxnet_cd_center.customer_service.service.IUserService;
import com.yxw.yxnet_cd_center.customer_service.service.SysMenuService;
import com.yxw.yxnet_cd_center.customer_service.utils.PageUtils;
import com.yxw.yxnet_cd_center.customer_service.vo.RoleVO;
import com.yxw.yxnet_cd_center.customer_service.vo.UserEmpVO;
import com.yxw.yxnet_cd_center.customer_service.vo.UserRuleVo;
import com.yxw.yxnet_cd_center.customer_service.vo.YxCsMenuVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 员工管理Service业务层处理
 *
 * @author xiexuxin
 * @date 2023-09-19
 */
@Slf4j
@Service
public class UserEmpServiceImpl extends ServiceImpl<UserMapper, YxCsUserEntity> implements IUserService {

    @Autowired
    private UserEmpMapper userMapper;

    @Autowired
    private RelevancyMapper relevancyMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private SysMenuService menuService;

    @Autowired
    private DeptMapper deptMapper;

    @Autowired
    private YxCsFlowRuleMapper yxCsFlowRuleMapper;

    @Autowired
    private YxCsGroupUserMapper yxCsGroupUserMapper;

    @Autowired
    private YxCsFlockUserMapper  yxCsFlockUserMapper;

    @Autowired
    private YxScFlowRuleUserMapper yxScFlowRuleUserMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addUser(UserEmpDTO empDTO) {
        log.info("开始处理【添加员工】的业务，参数：{}", empDTO);
        // 检查员工工号与员工电话是否已经存在
        LambdaQueryWrapper<YxCsUserEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(true, YxCsUserEntity::getUserNum, empDTO.getUserNum());
        Integer count = baseMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new BaseException("添加员工失败，尝试添加的员工工号重复！");
        }
        queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(true, YxCsUserEntity::getMobilePhone, empDTO.getMobilePhone());
        count = baseMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new BaseException("添加员工失败，尝试添加的员工电话重复！");
        }
        YxCsDeptEntity existingDept = deptMapper.selectById(empDTO.getDeptId());
        if (existingDept == null) {
            throw new BaseException("未找到ID为【" + empDTO.getDeptId() + "】的所属部门");
        }
        // 创建员工实体对象，并将DTO对象的属性复制到实体对象中
        YxCsUserEntity empEntity = new YxCsUserEntity();
        BeanUtil.copyProperties(empDTO, empEntity);
        empEntity.setUserName(empDTO.getUserName());
        empEntity.setNickName(PinyinUtill.getPinYinHeadChar(empDTO.getUserName()));
        empEntity.setUserStatus(null == empEntity.getUserStatus() ? 1 : empEntity.getUserStatus());
        empEntity.setHireDate(new Date());
        empEntity.setCreateTime(LocalDateTime.now());
        // 插入员工信息
        int rows = userMapper.insert(empEntity);
        if (rows != 1) {
            throw new BaseException("添加员工失败，服务器忙，请稍后再尝试！");
        }
        Long id = empEntity.getId();
        updatePassword(id, empDTO.getPassword());
        // 获取员工角色ID列表
        Long[] roleIds = empDTO.getRoleIds();
        if (roleIds.length > 0) {
            // 构建员工角色关联实体列表
            List<YxCsUserRoleEntity> userRoleList = new ArrayList<>();
            for (Long roleId : roleIds) {
                YxCsUserRoleEntity userRole = new YxCsUserRoleEntity();
                userRole.setUserId(empEntity.getId());
                userRole.setRoleId(roleId);
                userRoleList.add(userRole);
            }
            rows = userMapper.insertUserRoleBatch(userRoleList);
            if (rows < 1) {
                throw new BaseException("关联员工角色失败，服务器忙，请稍后再尝试！");
            }
            // 获取员工角色对应的菜单权限
            List<YxCsUserMenuEntity> userMenuList = new ArrayList<>();
            YxCsUserMenuEntity userMenu = new YxCsUserMenuEntity();
            Set<Long> menuIdSet = new HashSet<>();
            for (Long roleId : roleIds) {
                List<Long> menuIds = relevancyMapper.selectMenuIdsByRoleId(roleId);
                if (menuIds != null && !menuIds.isEmpty()) {
                    for (Long menuId : menuIds) {
                        addMenuAndParents(menuId, menuIdSet);
                    }
                }
            }
            if (menuIdSet.isEmpty()) {
                return;
            }
            Long[] menuIdArray = menuIdSet.toArray(new Long[0]);
            userMenu.setUserId(empEntity.getId());
            userMenu.setMenuIds(menuIdArray);
            userMenuList.add(userMenu);
            rows = relevancyMapper.insertUserMenus(userMenuList);
            if (rows < 1) {
                throw new BaseException("关联员工菜单失败，服务器忙，请稍后再尝试！");
            }
        }
    }

    // 查询菜单ID及其父节点ID的方法
    private Long selectParentIdByMenuId(Long menuId) {
        YxCsMenuEntity menu = menuService.selectMenuById(menuId);
        if (menu != null) {
            return menu.getParentId();
        }
        return null;
    }

    private void addMenuAndParents(Long menuId, Set<Long> menuIdSet) {
        Long parentId = selectParentIdByMenuId(menuId);
        if (parentId != null) {
            if (!menuIdSet.contains(parentId) && parentId != 0) {
                menuIdSet.add(parentId);
                addMenuAndParents(parentId, menuIdSet);
            }
        }
        if (!menuIdSet.contains(menuId) && menuId != 0) {
            menuIdSet.add(menuId);
        }
    }

    private void updatePassword(Long id, String password) {
        String newPassword = PasswordUtil.signUserPassword(id, password);
        LambdaUpdateWrapper<YxCsUserEntity> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(YxCsUserEntity::getUserId, id)
                .set(YxCsUserEntity::getPassword, newPassword);
        baseMapper.update(null, updateWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteUserById(Long id) {
        log.info("开始处理【删除员工】的业务，参数：{}", id);
        // 查询员工信息
        UserEmpVO queryResult = userMapper.selectUserById(id);
        // 删除员工和角色的关联信息
        relevancyMapper.deleteUserRoleByUserId(id);
        relevancyMapper.deleteUserMenuByUserId(id);
        if (queryResult == null || queryResult.getId() == 0) {
            throw new BaseException("删除员工失败，尝试删除的员工数据不存在！");
        }
        //校验人员是否存分配规则没有启用的人接
        List<Long> userIdList=new ArrayList<>();
        userIdList.add(id);
        List<UserRuleVo> voList=yxCsFlowRuleMapper.getNoUserRuleByIds(userIdList);
        if(null!=voList && !voList.isEmpty()){
            StringBuffer sbf =new StringBuffer();
            for (UserRuleVo vo :voList) {
                sbf.append ("人员【"+vo.getUserName()+"】在渠道【"+vo.getChannelName()+"】、端口【"+vo.getPortName()+"】、服务类型【"+vo.getServiceTypeName()+"】、规则【"+vo.getRuleTypeName()+"】下没有其余启用人员接收,不能修改删除<br>");
            }
            throw new BaseException(sbf.toString());
        }else{
            //工作组人员删除
            LambdaUpdateWrapper<YxCsGroupUserEntity> groupUserWrapper = new LambdaUpdateWrapper<>();
            groupUserWrapper.eq(true,YxCsGroupUserEntity::getUserId,id);
            yxCsGroupUserMapper.delete(groupUserWrapper);
            //删除群成员
            LambdaUpdateWrapper<YxCsFlockUserEntity> flockUserWrapper = new LambdaUpdateWrapper<>();
            flockUserWrapper.eq(true,YxCsFlockUserEntity::getUserId,id);
            yxCsFlockUserMapper.delete(flockUserWrapper);
            //删除规则人员
            LambdaUpdateWrapper<YxScFlowRuleUserEntity> ruleUserWrapper = new LambdaUpdateWrapper<>();
            ruleUserWrapper.eq(true,YxScFlowRuleUserEntity::getUserId,id);
            yxScFlowRuleUserMapper.delete(ruleUserWrapper);
        }
        // 删除员工信息
        int rows = userMapper.deleteById(id);
        if (rows != 1) {
            throw new BaseException("删除员工失败，服务器忙，请稍后再试！");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteUserByIds(List<Long> Ids) {
        log.info("开始处理【批量删除员工】的业务，参数：{}", Ids);

        if (Ids != null && !Ids.isEmpty()) {
            // 删除用户和角色的关联信息
            for (Long userId : Ids) {
                relevancyMapper.deleteUserRoleByUserId(userId);
                relevancyMapper.deleteUserMenuByUserId(userId);
            }
            // 批量删除用户信息
            int rows = userMapper.deleteUserByIds(Ids);
            if (rows != Ids.size()) {
                throw new BaseException("删除员工失败，服务器忙，请稍后再试！");
            }
        } else {
            throw new BaseException("删除员工失败，尝试删除的员工数据不存在！");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUser(Long id, UserEmpUpdateDTO empDTO) {
        log.info("开始处理【修改员工】的业务，参数：{}", empDTO);
        // 检查员工工号与员工电话是否已经存在
        LambdaQueryWrapper<YxCsUserEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(true, YxCsUserEntity::getUserNum, empDTO.getUserNum())
                    .ne(YxCsUserEntity::getId, id);
        Integer count = baseMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new BaseException("修改员工失败，尝试修改的员工工号重复！");
        }
        queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(true, YxCsUserEntity::getMobilePhone, empDTO.getMobilePhone())
                    .ne(YxCsUserEntity::getId, id);
        count = baseMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new BaseException("修改员工失败，尝试修改的员工电话重复！");
        }
        // 查询员工信息
        UserEmpVO queryResult = userMapper.selectUserById(id);
        if (queryResult == null || queryResult.getId() == 0) {
            throw new BaseException("修改员工失败，尝试修改的员工数据不存在！");
        }
        YxCsDeptEntity existingDept = deptMapper.selectById(empDTO.getDeptId());
        if (existingDept == null) {
            throw new BaseException("未找到ID为【" + empDTO.getDeptId() + "】的所属部门");
        }
        // 将DTO转化为Entity，并更新员工信息
        YxCsUserEntity empEntity = new YxCsUserEntity();
        BeanUtils.copyProperties(empDTO, empEntity);
        empEntity.setId(id);
        empEntity.setGender(empDTO.getGender());
        empEntity.setUpdateTime(LocalDateTime.now());
        int rows = userMapper.updateById(empEntity);
        if (rows != 1) {
            throw new BaseException("修改员工失败，服务器忙，请稍后再试！");
        }
        //禁用员工
        if(CommonConstant.ZERO!=empDTO.getUserStatus()){
            //校验人员是否存分配规则没有启用的人接
            List<Long> userIdList=new ArrayList<>();
            userIdList.add(id);
            List<UserRuleVo> voList=yxCsFlowRuleMapper.getNoUserRuleByIds(userIdList);
            if(null!=voList && !voList.isEmpty()){
                StringBuffer sbf =new StringBuffer();
                for (UserRuleVo vo :voList) {
                    sbf.append("当前员工存在渠道【"+vo.getChannelName()+"】、端口【"+vo.getPortName()+"】、服务类型【"+vo.getServiceTypeName()+"】、规则【"+vo.getRuleTypeName()+"】下没有其余启用人员接收,不能修改员工状态<br>");
                }
                throw new BaseException(sbf.toString());
            }
        }
        // 获取员工角色ID列表
        Long[] roleIds = empDTO.getRoleIds();
        // 删除原有角色关联, 并插入新的角色关联
        relevancyMapper.deleteUserRoleByUserId(id);
        // 删除原有菜单关联, 并插入新的菜单关联
        relevancyMapper.deleteUserMenuByUserId(id);
        if (roleIds.length > 0) {
            for (Long roleId : empDTO.getRoleIds()) {
                relevancyMapper.insertUserRole(id, roleId);
            }
            // 获取员工角色对应的菜单权限
            Set<Long> menuIdSet = new HashSet<>();
            for (Long roleId : roleIds) {
                List<Long> menuIds = relevancyMapper.selectMenuIdsByRoleId(roleId);
                if (menuIds != null && !menuIds.isEmpty()) {
                    for (Long menuId : menuIds) {
                        addMenuAndParents(menuId, menuIdSet);
                    }
                }
            }
            if (menuIdSet.isEmpty()) {
                return;
            }
            List<YxCsUserMenuEntity> userMenuList = new ArrayList<>();
            YxCsUserMenuEntity userMenu = new YxCsUserMenuEntity();
            userMenu.setUserId(empEntity.getId());
            userMenu.setMenuIds(menuIdSet.toArray(new Long[0])); // 将菜单ID及其父节点ID存入对象中
            userMenuList.add(userMenu);
            rows = relevancyMapper.insertUserMenus(userMenuList);
            if (rows < 1) {
                throw new BaseException("关联员工菜单失败，服务器忙，请稍后再尝试！");
            }
        }
    }

    @Override
    public void updateUserPicUrl(Long id, String picUrl) {
        LambdaUpdateWrapper<YxCsUserEntity> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(YxCsUserEntity::getId, id)
                .set(YxCsUserEntity::getPicUrl, picUrl)
                .set(YxCsUserEntity::getUpdateTime, LocalDateTime.now());
        int rows = baseMapper.update(null, updateWrapper);
        if (rows != 1) {
            throw new BaseException("修改员工头像失败，服务器忙，请稍后再试！");
        }
    }

    @Override
    public UserEmpVO selectUserById(Long id) {
        log.info("开始处理【根据id查询员工】的业务，参数：{}", id);
        return userMapper.selectUserById(id);
    }

    @Override
    public PageVO<UserEmpVO> getUserList(UserEmpQueryDTO empQueryDTO) {
        log.info("开始处理【条件查询员工列表】的业务，条件参数：{}", empQueryDTO);
        Page<UserEmpVO> page = new Page<>(empQueryDTO.getCurrPage(), empQueryDTO.getPageSize());
        List<UserEmpVO> list = userMapper.getUserEmpList(page, empQueryDTO);
        return PageUtils.get(page, list);
    }

    @Override
    public List<UserEmpVO> userList() {
        log.info("开始处理【查询员工列表】的业务，无参数");
        return userMapper.getAll();
    }

    @Override
    public void updateUserMenuByUserId(List<YxCsUserMenuEntity> userMenus) {
        log.info("开始处理【员工编辑权限】的业务，参数：{}", userMenus);
        for (YxCsUserMenuEntity userMenu : userMenus) {
            Long userId = userMenu.getUserId();
            relevancyMapper.deleteUserMenuByUserId(userId);
        }
        // 如果roleMenus中的menuIds为空，则不执行后续处理逻辑
        if (userMenus.stream().anyMatch(roleMenu -> roleMenu.getMenuIds() == null || roleMenu.getMenuIds().length == 0)) {
            return;
        }
        // 构建新的角色菜单关联关系
        Set<Long> menuIdSet = new HashSet<>();
        List<YxCsUserMenuEntity> newUserMenus = new ArrayList<>();
        for (YxCsUserMenuEntity userMenu : userMenus) {
            Long userId = userMenu.getUserId();
            Long[] menuIds = userMenu.getMenuIds();
            for (Long menuId : menuIds) {
                addMenuAndParents(menuId, menuIdSet);
            }
            Long[] menuIdArray = menuIdSet.toArray(new Long[0]);
            YxCsUserMenuEntity newUserMenu = new YxCsUserMenuEntity();
            newUserMenu.setUserId(userId);
            newUserMenu.setMenuIds(menuIdArray);
            newUserMenus.add(newUserMenu);
        }
        // 插入新的角色菜单关联关系
        relevancyMapper.insertUserMenus(newUserMenus);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean changePassword(Long id, PasswordDTO passwordDTO) {
        log.info("开始处理【修改密码】的业务，参数: {}", passwordDTO);
        // 根据用户ID查询用户信息
        YxCsUserEntity user = userMapper.selectById(id);
        if (user == null) {
            throw new BaseException("当前用戶不存在！");
        }
        // 验证当前密码是否正确
        if (!Objects.equals(PasswordUtil.signUserPassword(id, passwordDTO.getCurrentPassword()), user.getPassword())) {
            throw new BaseException("当前密码不正确");
        }
        // 验证新密码和确认密码是否一致
        if (!Objects.equals(PasswordUtil.signUserPassword(id, passwordDTO.getNewPassword()), PasswordUtil.signUserPassword(id, passwordDTO.getConfirmPassword()))) {
            throw new BaseException("新密码和确认密码不一致！");
        }
        // 更新密码和更新时间
        String newPassword = PasswordUtil.signUserPassword(id, passwordDTO.getNewPassword());
        LambdaUpdateWrapper<YxCsUserEntity> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(YxCsUserEntity::getUserId, id)
                .set(YxCsUserEntity::getPassword, newPassword)
                .set(YxCsUserEntity::getUpdateTime, LocalDateTime.now());
        int updateCount = baseMapper.update(null, updateWrapper);
        log.info("修改密码结果：{}", updateCount);
        return updateCount == 1;
    }

    @Override
    public List<YxCsMenuVo> getMenuTreeByUser(Long userId) {
        List<YxCsUserMenuEntity> userMenu = relevancyMapper.selectUserMenuByUserId(userId);
        if (userMenu.isEmpty()) {
            return null;
        }
        // 根据用户ID查询关联的菜单ID列表
        List<Long> menuIds = relevancyMapper.selectMenuIdsByUserId(userId).stream().distinct().collect(Collectors.toList());
        // 根据菜单ID列表查询菜单列表
        List<YxCsMenuEntity> menuList = userMapper.selectList(menuIds);
        List<YxCsMenuVo> menuVos = BeanUtil.copyToList(menuList, YxCsMenuVo.class);
        return buildMenuTree(menuVos, 0L);
    }

    @Override
    public List<YxCsMenuVo> getMenuTreeByUserMenu(Long userId) {
        List<RoleVO> roleList = roleMapper.selectRoleByUserId(userId);
        List<Long> roleIds = roleList.stream().map(RoleVO::getRoleId).collect(Collectors.toList());
        Set<Long> addedMenuIds = new HashSet<>(); // 保存已添加的菜单ID
        List<YxCsMenuVo> menuTree = new ArrayList<>();
        for (Long roleId : roleIds) {
            List<YxCsRoleMenuEntity> userRoleMenu = relevancyMapper.selectRoleMenuByRoleId(roleId);
            if (!userRoleMenu.isEmpty()) {
                // 根据角色ID查询关联的菜单ID列表
                List<Long> menuIds = relevancyMapper.selectMenuIdsByRoleId(roleId);
                List<YxCsMenuEntity> menuList = userMapper.selectList(menuIds);
                List<YxCsMenuVo> menuVos = BeanUtil.copyToList(menuList, YxCsMenuVo.class);
                // 构建菜单树
                List<YxCsMenuVo> roleMenuTree = buildMenuTree(menuVos, 0L);
                for (YxCsMenuVo menuVo : roleMenuTree) {
                    if (!addedMenuIds.contains(menuVo.getMenuId())) {
                        menuTree.add(menuVo);
                        addedMenuIds.add(menuVo.getMenuId());
                    }
                }
            }
        }
        return menuTree;
    }

    private List<YxCsMenuVo> buildMenuTree(List<YxCsMenuVo> menuVos, Long parentId) {
        List<YxCsMenuVo> tree = new ArrayList<>();
        for (YxCsMenuVo menuVo : menuVos) {
            if (parentId.equals(menuVo.getParentId())) {
                List<YxCsMenuVo> children = buildMenuTree(menuVos, menuVo.getMenuId());
                menuVo.setChildren(children);
                tree.add(menuVo);
            }
        }
        return tree;
    }

    @Override
    public List<UserEmpVO> workOrderList() {
        log.info("开始处理【查询工单中心列表】的业务，无参数");
        return userMapper.workOrderList();
    }

    @Override
    public PageVO<UserEmpVO> getWorkOrderList(UserEmpQueryDTO empQueryDTO) {
        log.info("开始处理【条件查询工单中心列表】的业务，条件参数：{}", empQueryDTO);
        Page<UserEmpVO> page = new Page<>(empQueryDTO.getCurrPage(), empQueryDTO.getPageSize());
        List<UserEmpVO> list = userMapper.getWorkOrderList(page, empQueryDTO);
        return PageUtils.get(page, list);
    }
}
